package service

import (
	"context"
	"fmt"
	"time"

	"github.com/slrun/callcenter/internal/model"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

// MonitorService 监控服务
type MonitorService struct {
	MongoDB          *mongo.Database
	RedisClient      interface{} // Redis客户端
	CallControlService *CallControlService
	AgentService     *AgentService
	ACDEngine        *ACDEngine
}

// NewMonitorService 创建监控服务实例
func NewMonitorService(mongoDB *mongo.Database, redisClient interface{}, callControlService *CallControlService, agentService *AgentService, acdEngine *ACDEngine) *MonitorService {
	return &MonitorService{
		MongoDB:          mongoDB,
		RedisClient:      redisClient,
		CallControlService: callControlService,
		AgentService:     agentService,
		ACDEngine:        acdEngine,
	}
}

// GetRealTimeMonitor 获取实时监控数据
func (s *MonitorService) GetRealTimeMonitor() (*model.RealTimeMonitor, error) {
	// 创建监控数据结构
	monitor := &model.RealTimeMonitor{
		Timestamp: time.Now(),
		CallMetrics: model.CallMetric{},
		AgentMetrics: model.AgentMetric{
			AgentStatusBreakdown: make(map[string]int64),
		},
		QueueMetrics: []model.QueueMetric{},
		SystemMetrics: model.SystemMetric{},
	}
	
	// 采集呼叫指标
	if err := s.collectCallMetrics(&monitor.CallMetrics); err != nil {
		return nil, fmt.Errorf("采集呼叫指标失败: %w", err)
	}
	
	// 采集座席指标
	if err := s.collectAgentMetrics(&monitor.AgentMetrics); err != nil {
		return nil, fmt.Errorf("采集座席指标失败: %w", err)
	}
	
	// 采集队列指标
	if err := s.collectQueueMetrics(&monitor.QueueMetrics); err != nil {
		return nil, fmt.Errorf("采集队列指标失败: %w", err)
	}
	
	// 采集系统指标
	if err := s.collectSystemMetrics(&monitor.SystemMetrics); err != nil {
		return nil, fmt.Errorf("采集系统指标失败: %w", err)
	}
	
	// 保存到历史记录
	go func() {
		s.saveMonitorHistory(monitor)
	}()
	
	return monitor, nil
}

// GenerateCallReport 生成呼叫报表
func (s *MonitorService) GenerateCallReport(startDate, endDate time.Time, period model.ReportPeriod) ([]model.CallReportData, error) {
	var reportData []model.CallReportData
	
	// 根据报表周期计算时间间隔
	interval := s.calculateInterval(period)
	
	// 遍历时间范围，收集每个时间段的数据
	current := startDate
	for current.Before(endDate) {
		next := current.Add(interval)
		if next.After(endDate) {
			next = endDate
		}
		
		// 收集时间段内的呼叫数据
		data, err := s.collectPeriodCallData(current, next, period)
		if err != nil {
			return nil, fmt.Errorf("收集时间段[%s-%s]呼叫数据失败: %w", current, next, err)
		}
		
		reportData = append(reportData, data)
		current = next
	}
	
	return reportData, nil
}

// GenerateAgentReport 生成座席报表
func (s *MonitorService) GenerateAgentReport(startDate, endDate time.Time, agentIDs []string) ([]model.AgentReportData, error) {
	var reportData []model.AgentReportData
	
	// 如果没有指定座席，获取所有座席
	if len(agentIDs) == 0 {
		// 修复ListAgents调用，匹配实际方法签名
		agents := s.AgentService.ListAgents()
		for _, agent := range agents {
			agentIDs = append(agentIDs, agent.ID)
		}
	}
	
	// 收集每个座席的数据
	for _, agentID := range agentIDs {
		data, err := s.collectAgentReportData(agentID, startDate, endDate)
		if err != nil {
			return nil, fmt.Errorf("收集座席[%s]报表数据失败: %w", agentID, err)
		}
		reportData = append(reportData, data)
	}
	
	return reportData, nil
}

// GenerateQueueReport 生成队列报表
func (s *MonitorService) GenerateQueueReport(startDate, endDate time.Time, queueIDs []string) ([]model.QueueReportData, error) {
	var reportData []model.QueueReportData
	
	// 如果没有指定队列，获取所有队列
	if len(queueIDs) == 0 {
		// 这里需要从ACD引擎获取队列列表
		// 暂时模拟获取队列ID
		queueIDs = []string{"sales", "support", "technical"}
	}
	
	// 收集每个队列的数据
	for _, queueID := range queueIDs {
		data, err := s.collectQueueReportData(queueID, startDate, endDate)
		if err != nil {
			return nil, fmt.Errorf("收集队列[%s]报表数据失败: %w", queueID, err)
		}
		reportData = append(reportData, data)
	}
	
	return reportData, nil
}

// CreateDashboardItem 创建仪表盘项目
func (s *MonitorService) CreateDashboardItem(userID string, item model.DashboardItem) (*model.DashboardItem, error) {
	// 设置ID和时间戳
	item.ID = fmt.Sprintf("DSH%d%d", time.Now().Unix(), time.Now().UnixNano()%1000)
	item.UserID = userID
	item.CreatedAt = time.Now()
	item.UpdatedAt = time.Now()
	
	// 保存到数据库
	collection := s.MongoDB.Collection("dashboard_items")
	if _, err := collection.InsertOne(context.Background(), item); err != nil {
		return nil, fmt.Errorf("创建仪表盘项目失败: %w", err)
	}
	
	return &item, nil
}

// GetDashboardItems 获取用户的仪表盘项目
func (s *MonitorService) GetDashboardItems(userID string) ([]model.DashboardItem, error) {
	collection := s.MongoDB.Collection("dashboard_items")
	filter := bson.M{"user_id": userID}
	
	cursor, err := collection.Find(context.Background(), filter)
	if err != nil {
		return nil, fmt.Errorf("获取仪表盘项目失败: %w", err)
	}
	defer cursor.Close(context.Background())
	
	var items []model.DashboardItem
	if err := cursor.All(context.Background(), &items); err != nil {
		return nil, fmt.Errorf("解析仪表盘项目数据失败: %w", err)
	}
	
	return items, nil
}

// UpdateDashboardItem 更新仪表盘项目
func (s *MonitorService) UpdateDashboardItem(userID, itemID string, updates map[string]interface{}) (*model.DashboardItem, error) {
	collection := s.MongoDB.Collection("dashboard_items")
	filter := bson.M{"_id": itemID, "user_id": userID}
	
	// 添加更新时间戳
	updates["updated_at"] = time.Now()
	
	update := bson.M{"$set": updates}
	result := collection.FindOneAndUpdate(context.Background(), filter, update)
	if result.Err() != nil {
		if result.Err() == mongo.ErrNoDocuments {
			return nil, fmt.Errorf("仪表盘项目不存在或无权修改")
		}
		return nil, fmt.Errorf("更新仪表盘项目失败: %w", result.Err())
	}
	
	// 获取更新后的项目
	var item model.DashboardItem
	if err := result.Decode(&item); err != nil {
		return nil, fmt.Errorf("获取更新后的仪表盘项目失败: %w", err)
	}
	
	return &item, nil
}

// DeleteDashboardItem 删除仪表盘项目
func (s *MonitorService) DeleteDashboardItem(userID, itemID string) error {
	collection := s.MongoDB.Collection("dashboard_items")
	filter := bson.M{"_id": itemID, "user_id": userID}
	
	result, err := collection.DeleteOne(context.Background(), filter)
	if err != nil {
		return fmt.Errorf("删除仪表盘项目失败: %w", err)
	}
	
	if result.DeletedCount == 0 {
		return fmt.Errorf("仪表盘项目不存在或无权删除")
	}
	
	return nil
}

// CreateAlert 创建监控告警
func (s *MonitorService) CreateAlert(alert model.MonitorAlert) (*model.MonitorAlert, error) {
	// 设置ID和时间戳
	alert.ID = fmt.Sprintf("ALT%d%d", time.Now().Unix(), time.Now().UnixNano()%1000)
	alert.CreatedAt = time.Now()
	alert.UpdatedAt = time.Now()
	
	// 保存到数据库
	collection := s.MongoDB.Collection("monitor_alerts")
	if _, err := collection.InsertOne(context.Background(), alert); err != nil {
		return nil, fmt.Errorf("创建告警失败: %w", err)
	}
	
	return &alert, nil
}

// GetAlerts 获取告警列表
func (s *MonitorService) GetAlerts(activeOnly bool) ([]model.MonitorAlert, error) {
	collection := s.MongoDB.Collection("monitor_alerts")
	filter := bson.M{}
	
	if activeOnly {
		filter["is_active"] = true
	}
	
	cursor, err := collection.Find(context.Background(), filter)
	if err != nil {
		return nil, fmt.Errorf("获取告警列表失败: %w", err)
	}
	defer cursor.Close(context.Background())
	
	var alerts []model.MonitorAlert
	if err := cursor.All(context.Background(), &alerts); err != nil {
		return nil, fmt.Errorf("解析告警数据失败: %w", err)
	}
	
	return alerts, nil
}

// UpdateAlert 更新告警
func (s *MonitorService) UpdateAlert(alertID string, updates map[string]interface{}) (*model.MonitorAlert, error) {
	collection := s.MongoDB.Collection("monitor_alerts")
	filter := bson.M{"_id": alertID}
	
	// 添加更新时间戳
	updates["updated_at"] = time.Now()
	
	update := bson.M{"$set": updates}
	result := collection.FindOneAndUpdate(context.Background(), filter, update)
	if result.Err() != nil {
		if result.Err() == mongo.ErrNoDocuments {
			return nil, fmt.Errorf("告警不存在")
		}
		return nil, fmt.Errorf("更新告警失败: %w", result.Err())
	}
	
	// 获取更新后的告警
	var alert model.MonitorAlert
	if err := result.Decode(&alert); err != nil {
		return nil, fmt.Errorf("获取更新后的告警失败: %w", err)
	}
	
	return &alert, nil
}

// GetAlertEvents 获取告警事件
func (s *MonitorService) GetAlertEvents(alertID string, limit int) ([]model.AlertEvent, error) {
	collection := s.MongoDB.Collection("alert_events")
	filter := bson.M{}
	
	if alertID != "" {
		filter["alert_id"] = alertID
	}
	
	// 设置排序和限制
	sort := bson.M{"created_at": -1}
	if limit <= 0 {
		limit = 100
	}
	
	// 修复FindOptions的使用
	findOptions := options.Find()
	findOptions.SetSort(sort)
	findOptions.SetLimit(int64(limit))
	cursor, err := collection.Find(context.Background(), filter, findOptions)
	if err != nil {
		return nil, fmt.Errorf("获取告警事件失败: %w", err)
	}
	defer cursor.Close(context.Background())
	
	var events []model.AlertEvent
	if err := cursor.All(context.Background(), &events); err != nil {
		return nil, fmt.Errorf("解析告警事件数据失败: %w", err)
	}
	
	return events, nil
}

// 内部方法：采集呼叫指标
func (s *MonitorService) collectCallMetrics(metrics *model.CallMetric) error {
	// 这里应该从数据库或实时数据源获取实际数据
	// 暂时使用模拟数据
	metrics.TotalCalls = 150
	metrics.InboundCalls = 120
	metrics.OutboundCalls = 30
	metrics.AnsweredCalls = 140
	metrics.MissedCalls = 5
	metrics.AbandonedCalls = 5
	metrics.TransferCalls = 15
	metrics.ConferenceCalls = 8
	metrics.AvgWaitTime = 25.6
	metrics.AvgTalkTime = 180.5
	metrics.AvgWrapUpTime = 60.2
	metrics.ServiceLevel = 93.5
	metrics.AbandonRate = 3.3
	metrics.AnswerRate = 93.3
	
	return nil
}

// 内部方法：采集座席指标
func (s *MonitorService) collectAgentMetrics(metrics *model.AgentMetric) error {
	// 这里应该从座席服务获取实际数据
	// 修复ListAgents调用，匹配实际方法签名
	agents := s.AgentService.ListAgents()
	
	metrics.TotalAgents = int64(len(agents))
	
	// 统计各状态座席数量
	for _, agent := range agents {
		metrics.AgentStatusBreakdown[string(agent.Status)]++
		
		switch agent.Status {
		case model.AgentStatusLoggedIn:
			metrics.LoggedInAgents++
		case model.AgentStatusAvailable:
			metrics.AvailableAgents++
			metrics.LoggedInAgents++
		case model.AgentStatusBusy:
			metrics.BusyAgents++
			metrics.LoggedInAgents++
		case model.AgentStatusWrapup:
			metrics.WrapUpAgents++
			metrics.LoggedInAgents++
		case model.AgentStatusOnBreak:
			metrics.UnavailableAgents++
			metrics.LoggedInAgents++
		}
	}
	
	return nil
}

// 内部方法：采集队列指标
func (s *MonitorService) collectQueueMetrics(queueMetrics *[]model.QueueMetric) error {
	// 这里应该从ACD引擎获取实际的队列数据
	// 暂时使用模拟数据
	queues := []model.QueueMetric{
		{
			QueueName:       "sales",
			WaitingCalls:    3,
			LongestWaitTime: 120,
			AvgWaitTime:     45.5,
			AgentsLoggedIn:  8,
			AgentsAvailable: 2,
			ServiceLevel:    90.0,
			AbandonRate:     2.5,
		},
		{
			QueueName:       "support",
			WaitingCalls:    5,
			LongestWaitTime: 180,
			AvgWaitTime:     65.2,
			AgentsLoggedIn:  12,
			AgentsAvailable: 1,
			ServiceLevel:    85.0,
			AbandonRate:     4.0,
		},
		{
			QueueName:       "technical",
			WaitingCalls:    2,
			LongestWaitTime: 90,
			AvgWaitTime:     35.8,
			AgentsLoggedIn:  6,
			AgentsAvailable: 3,
			ServiceLevel:    95.0,
			AbandonRate:     1.0,
		},
	}
	
	*queueMetrics = queues
	return nil
}

// 内部方法：采集系统指标
func (s *MonitorService) collectSystemMetrics(metrics *model.SystemMetric) error {
	// 这里应该从系统监控工具获取实际数据
	// 暂时使用模拟数据
	metrics.CPULoad = 35.6
	metrics.MemoryUsage = 65.2
	metrics.DiskUsage = 45.8
	metrics.NetworkIn = 524288.0 // 512 KB/s
	metrics.NetworkOut = 262144.0 // 256 KB/s
	metrics.ActiveCalls = 45
	metrics.ActiveIVRs = 12
	metrics.DatabaseConnections = 25
	metrics.RedisConnections = 18
	
	return nil
}

// 内部方法：保存监控历史
func (s *MonitorService) saveMonitorHistory(monitor *model.RealTimeMonitor) {
	collection := s.MongoDB.Collection("monitor_history")
	_, err := collection.InsertOne(context.Background(), monitor)
	if err != nil {
		// 记录错误但不影响主流程
		fmt.Printf("保存监控历史失败: %v\n", err)
	}
}

// 内部方法：计算时间间隔
func (s *MonitorService) calculateInterval(period model.ReportPeriod) time.Duration {
	switch period {
	case model.ReportPeriodHourly:
		return time.Hour
	case model.ReportPeriodDaily:
		return 24 * time.Hour
	case model.ReportPeriodWeekly:
		return 7 * 24 * time.Hour
	case model.ReportPeriodMonthly:
		// 简化处理，使用30天
		return 30 * 24 * time.Hour
	default:
		return time.Hour
	}
}

// 内部方法：收集时间段内的呼叫数据
func (s *MonitorService) collectPeriodCallData(startTime, endTime time.Time, period model.ReportPeriod) (model.CallReportData, error) {
	// 这里应该从数据库查询实际数据
	// 暂时使用模拟数据
	periodStr := startTime.Format("2006-01-02 15:04")
	if period == model.ReportPeriodDaily {
		periodStr = startTime.Format("2006-01-02")
	}
	
	data := model.CallReportData{
		Period:          periodStr,
		TotalCalls:      120 + int64(startTime.Hour()), // 模拟数据
		InboundCalls:    90 + int64(startTime.Hour()),
		OutboundCalls:   30,
		AnsweredCalls:   110 + int64(startTime.Hour()),
		MissedCalls:     5,
		AbandonedCalls:  5,
		TransferCalls:   10,
		ConferenceCalls: 5,
		AvgWaitTime:     20.5 + float64(startTime.Minute())*0.1,
		AvgTalkTime:     150.2,
		AvgWrapUpTime:   50.8,
		ServiceLevel:    90.0 + float64(startTime.Hour())*0.5,
		AbandonRate:     4.0,
		AnswerRate:      92.0,
		StartTime:       startTime,
		EndTime:         endTime,
	}
	
	return data, nil
}

// 内部方法：收集座席报表数据
func (s *MonitorService) collectAgentReportData(agentID string, startDate, endDate time.Time) (model.AgentReportData, error) {
	// 获取座席信息 - 使用正确的方法名
	_, err := s.AgentService.GetAgent(agentID)
	if err != nil {
		return model.AgentReportData{}, err
	}
	
	// 这里应该从数据库查询实际数据
	// 暂时使用模拟数据
	data := model.AgentReportData{
		AgentID:                 agentID,
		LoggedInTime:            480.0, // 8小时
		AvailableTime:           180.0,
		BusyTime:                240.0,
		WrapUpTime:              60.0,
		BreakTime:               30.0,
		HandledCalls:            25 + int64(len(agentID)%10),
		AvgTalkTime:             180.0,
		AvgWrapUpTime:           65.0,
		TransferIn:              2,
		TransferOut:             3,
		FirstCallResolutionRate: 85.5,
		CustomerSatisfactionScore: 4.5,
	}
	
	return data, nil
}

// 内部方法：收集队列报表数据
func (s *MonitorService) collectQueueReportData(queueID string, startDate, endDate time.Time) (model.QueueReportData, error) {
	// 这里应该从数据库查询实际数据
	// 暂时使用模拟数据
	data := model.QueueReportData{
		QueueID:         queueID,
		QueueName:       queueID,
		CallsOffered:    100 + int64(len(queueID)*10),
		CallsAnswered:   90 + int64(len(queueID)*10),
		CallsAbandoned:  10,
		CallsOverflowed: 5,
		AvgWaitTime:     30.5 + float64(len(queueID)*5),
		MaxWaitTime:     300.0,
		AvgTalkTime:     150.0,
		ServiceLevel:    85.0 + float64(len(queueID)*2),
		AbandonRate:     10.0,
		AnswerRate:      90.0,
		AgentsLoggedIn:  8.0,
		AgentsAvailable: 3.0,
	}
	
	return data, nil
}

// 内部方法：触发告警通知
func (s *MonitorService) triggerAlert(alertID string, alertName string, metric string, currentValue float64, threshold float64, condition string, severity string) error {
	// 创建告警事件
	event := model.AlertEvent{
		ID:            fmt.Sprintf("AEV%d%d", time.Now().Unix(), time.Now().UnixNano()%1000),
		AlertID:       alertID,
		AlertName:     alertName,
		Metric:        metric,
		CurrentValue:  currentValue,
		Threshold:     threshold,
		Condition:     condition,
		Severity:      severity,
		Status:        "triggered",
		Details:       make(map[string]interface{}),
		TriggeredAt:   time.Now(),
	}
	
	// 保存告警事件
	collection := s.MongoDB.Collection("alert_events")
	if _, err := collection.InsertOne(context.Background(), event); err != nil {
		return fmt.Errorf("保存告警事件失败: %w", err)
	}
	
	// 发送通知（这里应该实现实际的通知逻辑）
	fmt.Printf("触发告警: %s - %s 当前值: %.2f 阈值: %.2f 条件: %s\n", 
		alertName, metric, currentValue, threshold, condition)
	
	return nil
}

// 内部方法：解决告警
func (s *MonitorService) resolveAlert(alertID string) error {
	collection := s.MongoDB.Collection("alert_events")
	filter := bson.M{
		"alert_id": alertID,
		"status":   "triggered",
	}
	update := bson.M{
		"$set": bson.M{
			"status":     "resolved",
			"resolved_at": time.Now(),
		},
	}
	
	result, err := collection.UpdateOne(context.Background(), filter, update)
	if err != nil {
		return fmt.Errorf("更新告警事件状态失败: %w", err)
	}
	
	if result.MatchedCount == 0 {
		return fmt.Errorf("没有找到待解决的告警事件")
	}
	
	return nil
}